﻿#region The MIT License (MIT)
// The MIT License (MIT)
// Copyright (c) 2010 - 2013 Sovacode LLC
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated 
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in all copies or substantial portions
// of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#endregion


using System.Collections.Generic;
using System.Linq;

/* Importing namespaces */
using Sovacode.DemoApp.Commands;
using Sovacode.RubiksCube.Common.Managers.Settings.Data;
using Sovacode.RubiksCube.Common.Collections;
using Sovacode.RubiksCube.Common.Managers.Validation;

namespace Sovacode.DemoApp.ViewModel
{
    /// <summary>
    /// View Model of Connection strings
    /// </summary>
    public sealed class ConnectionStringsViewModel /*
                                                    * Demonstration how to store connection strings in config file.
                                                    * The connection strings will stores in XML foramt with UTF-8 encoding.
                                                    * 
                                                    * !!!!!
                                                    * 
                                                    * WARNING: It's not good practise to store password in connection string.
                                                    * 
                                                    * !!!!!
                                                    */
        : BasicViewModel.ChildsHolderViewModel
    {
        #region Private Fields

        /// <summary>
        /// The connections
        /// </summary>
        private AdvancedObservableCollection<DataAccessSetting> _connections;

        /// <summary>
        /// The selected connection
        /// </summary>
        private DataAccessSetting _selectedConnection;

        private string _name;
        private string _connectionString;
        private bool _isDefault;
        private bool _needToAskPass;

        #endregion

        #region Private Methods

        /// <summary>
        /// Gets the data access settings.
        /// </summary>
        /// <value>The data access settings.</value>
        private IEnumerable<DataAccessSetting> DataAccessSettings
        {
            get { return SettingsManager.LoadConnectionStrings(); }
        }

        /// <summary>
        /// Creates the connections collection.
        /// </summary>
        /// <returns>AdvancedObservableCollection{DataAccessSetting}.</returns>
        private AdvancedObservableCollection<DataAccessSetting> LoadConnectionsSettings()
        {
            var connections = new AdvancedObservableCollection<DataAccessSetting>();

            if (DataAccessSettings.Any())
            {
                connections.AddRange(DataAccessSettings);
            }

            if (connections.Count == 0)
            {
                connections.Add(new DataAccessSetting
                                    {
                                        Name = "Standard Security",
                                        ConnectionString = "Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;",
                                        Default = true,
                                        NeedToAskPassword = true
                                    });
            }

            return connections;
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets or sets the name.
        /// </summary>
        /// <value>The name.</value>
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;

                OnPropertyChanged(() => Name);
            }
        }

        /// <summary>
        /// Gets or sets the connection string.
        /// </summary>
        /// <value>The connection string.</value>
        public string ConnectionString
        {
            get { return _connectionString; }
            set
            {
                _connectionString = value;

                OnPropertyChanged(() => ConnectionString);
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is default.
        /// </summary>
        /// <value><c>true</c> if this instance is default; otherwise, <c>false</c>.</value>
        public bool IsDefault
        {
            get { return _isDefault; }
            set
            {
                _isDefault = value;

                OnPropertyChanged(() => IsDefault);
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether [need to ask pass].
        /// </summary>
        /// <value><c>true</c> if [need to ask pass]; otherwise, <c>false</c>.</value>
        public bool NeedToAskPass
        {
            get { return _needToAskPass; }
            set
            {
                _needToAskPass = value;

                OnPropertyChanged(() => NeedToAskPass);
            }
        }

        /// <summary>
        /// Gets the connections.
        /// </summary>
        /// <value>The connections.</value>
        public AdvancedObservableCollection<DataAccessSetting> Connections
        {
            get { return _connections ?? (_connections = LoadConnectionsSettings()); }
        }

        /// <summary>
        /// Gets or sets the selected connection.
        /// </summary>
        /// <value>The selected connection.</value>
        public DataAccessSetting SelectedConnection
        {
            get { return _selectedConnection; }
            set
            {
                _selectedConnection = value;

                OnPropertyChanged(() => SelectedConnection);

                Refresh();
            }
        }
        
        #endregion

        #region Commands

        /// <summary>
        /// Refresh
        /// </summary>
        protected override void Refresh()
        {
            base.Refresh();

            if (SelectedConnection == null)
            {
                Name = string.Empty;
                ConnectionString = string.Empty;
                IsDefault = false;
                NeedToAskPass = true;
                
                return;
            }

            Name = SelectedConnection.Name;
            ConnectionString = SelectedConnection.ConnectionString;
            IsDefault = SelectedConnection.Default;
            NeedToAskPass = SelectedConnection.NeedToAskPassword;

        }

        /// <summary>
        /// Creates the new connection.
        /// </summary>
        private void CreateNewConnection()
        {
            Connections.Add(new DataAccessSetting
                                {
                                    Name = Name,
                                    ConnectionString = ConnectionString,
                                    Default = IsDefault,
                                    NeedToAskPassword = NeedToAskPass
                                });
        }

        /// <summary>
        /// Saves the current connection.
        /// </summary>
        private void SaveCurrentConnection()
        {
            if (SelectedConnection == null)
            {
                return;
            }

            SelectedConnection.Name = Name;
            SelectedConnection.ConnectionString = ConnectionString;
            SelectedConnection.Default = IsDefault;
            SelectedConnection.NeedToAskPassword = NeedToAskPass;
        }

        /// <summary>
        /// Removes the current connection.
        /// </summary>
        private void RemoveCurrentConnection()
        {
            if (SelectedConnection == null)
            {
                return;
            }

            if (Connections.Contains(SelectedConnection))
            {
                Connections.Remove(SelectedConnection);
            }
        }

        /// <summary>
        /// Clears all.
        /// </summary>
        private void ClearAll()
        {
            SelectedConnection = null;

            Connections.Clear();
        }

        #endregion

        #region Override


        /// <summary>
        /// Gets the description file.
        /// </summary>
        /// <value>The description file.</value>
        protected override string DescriptionFile
        {
            get { return "ConnectionStringsDescription.txt"; }
        }

        /// <summary>
        /// Load Settings
        /// </summary>
        public override void LoadSettings()
        {
            base.LoadSettings();

            LoadConnectionsSettings();
        }

        /// <summary>
        /// Save settings
        /// </summary>
        protected override void SaveSettings()
        {
            SettingsManager.SaveConnectionString(Connections.ToList());

            base.SaveSettings();
        }

        /// <summary>
        /// Method where the commands should be registered.
        /// </summary>
        protected override void RegisterCommands()
        {
            base.RegisterCommands();

            RegisterCommand(Const.ConnectionStringsView.CreateNewConnection, o => CreateNewConnection(), p => IsValid);
            RegisterCommand(Const.ConnectionStringsView.SaveOldConnection, o => SaveCurrentConnection(), p => SelectedConnection != null);
            RegisterCommand(Const.ConnectionStringsView.RemoveOldConnection, o => RemoveCurrentConnection(), p => SelectedConnection != null);
            RegisterCommand(Const.ConnectionStringsView.ClearAll, o => ClearAll(), p => Connections != null && Connections.Count > 0);
        }

        /// <summary>
        /// Registration of <see cref="ValidationRule" /> begins here. You should use it in all objects with validation.
        /// </summary>
        protected override void RegisterValidationRules()
        {
            base.RegisterValidationRules();

            RegisterRule(() => Name, () => !string.IsNullOrWhiteSpace(Name), "Name can not be empty!");
            RegisterRule(() => ConnectionString, () => !string.IsNullOrWhiteSpace(ConnectionString), "Connection string can not be empty!");
        }

        #endregion

    }
}